package com.lmq.utils;

import com.alibaba.fastjson.JSONObject;

import java.util.*;

public class Bot implements com.lmq.utils.BotInterface {

    static class Cell {
        public int x, y;
        public Cell(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    private int[][] g;
    private Integer asx, asy, bsx, bsy;
    private String aSteps;
    private String bSteps;
    private List<Cell> aCells;
    private List<Cell> bCells;

    int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};

    private boolean check_tail_increasing(int step) {
        if (step <= 10) return true;
        return step % 3 == 1;
    }

    public List<Cell> getCells(int sx, int sy, String steps) {
        List<Cell> res = new ArrayList<>();

        int x = sx, y = sy;
        int step = 0;
        res.add(new Cell(x, y));
        for(int i = 0; i < steps.length(); i ++ ) {
            int d = steps.charAt(i) - '0';
            x += dx[d];
            y += dy[d];
            res.add(new Cell(x, y));
            if(!check_tail_increasing( ++ step)) {
                res.remove(0);
            }
        }
        return res;
    }

    public void getData(String input) {
        JSONObject msg = JSONObject.parseObject(input);
        String map = msg.get("map").toString();
        Integer asx = (Integer) msg.get("me_sx");
        Integer asy = (Integer) msg.get("me_sy");
        String aSteps = msg.get("me_steps").toString();

        Integer bsx = (Integer) msg.get("me_sx");
        Integer bsy = (Integer) msg.get("me_sy");
        String bSteps = msg.get("me_steps").toString();

        this.g = new int[13][14];
        for(int i = 0, k = 0; i < 13; i++) {
            for(int j = 0; j < 14; j++, k++) {
                if(map.charAt(k) == '1') {
                    g[i][j] = 1;
                }
            }
        }

        this.asx = asx;
        this.asy = asy;
        this.bsx = bsx;
        this.bsy = bsy;

        this.aCells = getCells(asx, asy, aSteps);
        this.bCells = getCells(bsx, bsy, bSteps);
    }

//    public Integer nextMove(String input) {
//
//        getData(input);
//
//        for(Cell c: aCells) g[c.x][c.y] = 1;
//        for(Cell c: bCells) g[c.x][c.y] = 1;
//
//        int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
//        for(int i = 0; i < 4; i ++ ) {
//            int x = aCells.get(aCells.size() - 1).x + dx[i];
//            int y = aCells.get(aCells.size() - 1).y + dy[i];
//            if (x >= 0 && x < 13 && y >= 0 && y < 14 && g[x][y] == 0) {
//                return i;
//            }
//        }
//        return 0;
//    }






    public Integer nextMove(String input) {
        getData(input);

        int maxDepth = 3; // 设置搜索深度

        for (Cell c : aCells) g[c.x][c.y] = 1;
        for (Cell c : bCells) g[c.x][c.y] = 1;

        int bestMove = 0;
        int bestScore = Integer.MIN_VALUE;
        Cell head = aCells.get(aCells.size() - 1);

        for (int i = 0; i < 4; i++) {
            int nx = head.x + dx[i];
            int ny = head.y + dy[i];
            if (nx >= 0 && nx < 13 && ny >= 0 && ny < 14 && g[nx][ny] == 0) {
                g[nx][ny] = 1;
                aCells.add(new Cell(nx, ny)); // 更新aCells
                int score = alphaBeta(g, maxDepth, Integer.MIN_VALUE, Integer.MAX_VALUE, false);
                aCells.remove(aCells.size() - 1); // 撤回aCells
                g[nx][ny] = 0; // 还原

                if (score > bestScore) {
                    bestScore = score;
                    bestMove = i;
                }
            }
        }

        return bestMove;
    }

    private int alphaBeta(int[][] g, int depth, int alpha, int beta, boolean isMaximizingPlayer) {
        if (depth == 0 || isGameOver(g)) {
            return evaluate(g);
        }

        if (isMaximizingPlayer) {
            int maxEval = Integer.MIN_VALUE;
            Cell head = aCells.get(aCells.size() - 1);
            for (int i = 0; i < 4; i++) {
                int nx = head.x + dx[i];
                int ny = head.y + dy[i];
                if (nx >= 0 && nx < 13 && ny >= 0 && ny < 14 && g[nx][ny] == 0) {
                    g[nx][ny] = 1; // 试探走这一步
                    aCells.add(new Cell(nx, ny)); // 更新aCells
                    int eval = alphaBeta(g, depth - 1, alpha, beta, false);
                    aCells.remove(aCells.size() - 1); // 撤回aCells
                    g[nx][ny] = 0; // 撤回这一步
                    maxEval = Math.max(maxEval, eval);
                    alpha = Math.max(alpha, eval);
                    if (beta <= alpha) {
                        break;
                    }
                }
            }
            return maxEval;
        } else {
            int minEval = Integer.MAX_VALUE;
            Cell head = bCells.get(bCells.size() - 1);
            for (int i = 0; i < 4; i++) {
                int nx = head.x + dx[i];
                int ny = head.y + dy[i];
                if (nx >= 0 && nx < 13 && ny >= 0 && ny < 14 && g[nx][ny] == 0) {
                    g[nx][ny] = 1; // 试探走这一步
                    bCells.add(new Cell(nx, ny)); // 更新bCells
                    int eval = alphaBeta(g, depth - 1, alpha, beta, true);
                    bCells.remove(bCells.size() - 1); // 撤回bCells
                    g[nx][ny] = 0; // 撤回这一步
                    minEval = Math.min(minEval, eval);
                    beta = Math.min(beta, eval);
                    if (beta <= alpha) {
                        break;
                    }
                }
            }
            return minEval;
        }
    }

    private int evaluate(int[][] g) {
        // 评估函数：返回当前局面下的评分
        // 这里假设简单地以蛇a能占据的安全区域大小作为评分
        Cell head = aCells.get(aCells.size() - 1);
        return floodFill(head.x, head.y);
    }

    private boolean isGameOver(int[][] g) {
        // 判断游戏是否结束
        // 这里简单地判断蛇头是否有任何合法移动
        Cell head = aCells.get(aCells.size() - 1);
        for (int i = 0; i < 4; i++) {
            int nx = head.x + dx[i];
            int ny = head.y + dy[i];
            if (nx >= 0 && nx < 13 && ny >= 0 && ny < 14 && g[nx][ny] == 0) {
                return false;
            }
        }
        return true;
    }

    private int floodFill(int x, int y) {
        boolean[][] visited = new boolean[13][14];
        Queue<Cell> queue = new LinkedList<>();
        queue.add(new Cell(x, y));
        visited[x][y] = true;
        int area = 0;

        while (!queue.isEmpty()) {
            Cell current = queue.poll();
            area++;
            for(int i = 0; i < 4; i++) {
                int nx = current.x + dx[i];
                int ny = current.y + dy[i];
                if (nx >= 0 && nx < 13 && ny >= 0 && ny < 14 && g[nx][ny] == 0 && !visited[nx][ny]) {
                    queue.add(new Cell(nx, ny));
                    visited[nx][ny] = true;
                }
            }
        }

        return area;
    }
}




